package org.testis.communication.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;

/**
 * A class to define a tcp server
 * @author nurhat
 */
public class AtofTcpServer {

    private ServerSocket m_serverSocket;
    private int m_keepAliveTime;
    private int m_portNumber;
    private StringBuilder m_lastError;

    /**
     * Create tcp server object
     * @param keepAliveTime defines timeout for waiting a client
     * @param portNumber
     */
    public AtofTcpServer(int keepAliveTime,
            int portNumber) {
        m_keepAliveTime = keepAliveTime;
        m_portNumber = portNumber;
        m_lastError=new StringBuilder();

    }

    /**
     * Waits a client for given timeout value.
     * Echos back any message recieved from a client
     * @return message of client and close its connection
     * @throws java.net.SocketException
     * @throws java.io.IOException
     */
    public String waitForClientMessage() {
        String result = null;
        try {
            m_serverSocket = new ServerSocket();
            m_serverSocket.setSoTimeout(m_keepAliveTime);
            SocketAddress address = new InetSocketAddress(m_portNumber);
            m_serverSocket.setReuseAddress(true);
            m_serverSocket.bind(address);
            Socket clientSocket = waitForClientToConnect();
            result = readClientMsg(clientSocket);
        }  catch (SocketTimeoutException ex) {
             m_lastError.append("No client connected to server.Server timed out...");
        } catch (IOException ex) {
            m_lastError.append(ex.toString());
        }  catch (Exception ex) {
             m_lastError.append(ex.toString());
        } finally {
            try {
                if (m_serverSocket != null) {
                    m_serverSocket.close();
                }
            } catch (IOException ex) {
            } catch (Exception ex) {
            }
        }
        return result;
    }

    private Socket waitForClientToConnect() throws IOException {
        return m_serverSocket.accept();
    }

    private String readClientMsg(Socket clientSocket) {
        DataInputStream in = null;
        String data = null;
        DataOutputStream out = null;
        try {
            in = new DataInputStream(clientSocket.getInputStream());
            out = new DataOutputStream(clientSocket.getOutputStream());
            data = in.readUTF();
            //echo back the message
            out.writeUTF(data);
        } catch (IOException ex) {
             m_lastError.append(ex.toString());
        } catch (Exception ex) {
             m_lastError.append(ex.toString());
        } finally {
            try {
                if (clientSocket != null) {
                    clientSocket.close();
                }
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
            } catch (Exception ex) {
            }
        }
        return data;
    }

    /**
     * @return the m_lastError
     */
    public String getLastError() {
        return m_lastError.toString();
    }
}
